package com.lw.controller;

import ch.qos.logback.core.util.StringUtil;
import cn.dev33.satoken.annotation.SaIgnore;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.crypto.symmetric.DES;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.lw.common.other.LogOperation;
import com.lw.common.utils.ResultVo;
import com.lw.common.vo.MenuVo;
import com.lw.common.vo.PasswordVo;
import com.lw.entity.*;
import com.lw.service.*;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.crypto.SecretKey;
import java.time.LocalDateTime;
import java.util.List;

import static com.lw.entity.table.TbUserTableDef.TB_USER;

/**
 * 控制层。
 *
 * @author lw
 * @since 2024年08月03日 18:20:52
 */
@RestController
@RequestMapping("/tbUser")
@Tag(name = "租户接口", description = "1-租户接口")
public class TbUserController {

    private final Logger log = LoggerFactory.getLogger(TbUserController.class);

    @Resource
    private TbUserService tbUserService;

    @Resource
    private TbRoleService tbRoleService;

    @Resource
    private TbInterfaceService tbInterfaceService;

    @Resource
    private TbKeyService tbKeyService;

    @Resource
    private TbUserInterfaceService tbUserInterfaceService;

    public static void main(String[] args) {

        String key = "china_qx@58140";
        SecretKey secretKey = SecureUtil.generateKey(SymmetricAlgorithm.DES.getValue(), key.getBytes());
        System.out.println("secretKey=" + new String(secretKey.getEncoded()));
        DES des = SecureUtil.des(secretKey.getEncoded());
        //加密
        String encryptStr = des.encryptHex("hello world , lw");
        System.out.println(encryptStr);
        //解密
        String s = des.decryptStr("aa7d30dfd8e45d50ec7785a54d4267b3aa3d402819595b37");
        System.out.println(s);
    }

    @SaIgnore
    @PostMapping("doLogin")
    @Operation(summary = "租户登录")
    @LogOperation("租户-登录")
    public ResultVo<SaTokenInfo> doLogin(@RequestBody TbUser user) {
        if (StringUtil.isNullOrEmpty(user.getLoginName()) || StringUtil.isNullOrEmpty(user.getPassword())) {
            log.error("参数不能为空");
            return ResultVo.error("参数不能为空");
        }
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("login_name", user.getLoginName());
        queryWrapper.eq("password", DigestUtil.md5Hex16(user.getPassword()));
        TbUser one = tbUserService.getOne(queryWrapper);
        if (one != null && one.getId() > 0) {
            StpUtil.login(one.getId());
        } else {
            log.error("账户或密码错误");
            return ResultVo.error("账户或密码错误");
        }
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        log.info("登录成功");
        return ResultVo.success("登录成功", tokenInfo);
    }

    @GetMapping("logOut")
    @LogOperation("租户-退出登录")
    public ResultVo<String> logOut() {
        String loginId = StpUtil.getLoginIdAsString();
        if (StringUtils.hasLength(loginId)) {
            // 执行退出操作
            StpUtil.logout(loginId);
            return ResultVo.success("退出成功");
        } else {
            return ResultVo.error("用户未登录，无需退出");
        }
    }


    @GetMapping("isLogin")
    @Operation(summary = "是否登录")
    public ResultVo<Boolean> isLogin() {
        boolean login = StpUtil.isLogin();
        return ResultVo.success(login);
    }

    @Operation(summary = "获取当前租户绑定的接口列表")
    @GetMapping("getUserDetail")
    public ResultVo<TbUser> getUserDetail(@RequestParam(name = "userId", required = false) Integer userId) {
        if (userId == null) {
            userId = StpUtil.getLoginIdAsInt();
        }
        TbUser tbUser = tbUserService.getById(userId);
        Integer roleId = tbUser.getRoleId();
        if (roleId != null) {
            TbRole tbRole = tbRoleService.getById(roleId);
            tbUser.setTbRole(tbRole);
        }
        List<TbInterface> tbInterfaceList = tbInterfaceService.getInterfaceByUserId(userId);
        tbUser.setTbInterfaceList(tbInterfaceList);
        // 获取当前用户密钥
        Integer keyId = tbUser.getKeyId();
        if (keyId!= null) {
            TbKey tbKey = tbKeyService.getById(keyId);
            if (tbKey!= null) {
                tbUser.setTbKey(tbKey);
            }
        }
        return ResultVo.success(tbUser);
    }

    @Operation(summary = "获取当前租户角色，权限等信息")
    @GetMapping("getUserPermission")
    public ResultVo<TbUser> getUserPermission() {
        Integer loginId = StpUtil.getLoginIdAsInt();
        if (loginId == null) {
            return ResultVo.error("未登录");
        }
        TbUser tbUser = tbUserService.getById(loginId);
        Integer roleId = tbUser.getRoleId();
        TbRole tbRole = tbRoleService.getById(roleId);
        tbUser.setTbRole(tbRole);
        List<TbMenu> tbMenuList = tbUserService.getUserPermission(roleId);
        tbUser.setTbMenuList(tbMenuList);
        return ResultVo.success(tbUser);
    }

    /**
     * 添加。
     *
     * @param tbUser
     * @return {@code true} 添加成功，{@code false} 添加失败
     */
    @PostMapping("save")
    @LogOperation("租户-保存")
    @Operation(summary = "租户保存", description = "租户保存")
    public ResultVo<Integer> save(@RequestBody TbUser tbUser) {
        if (StringUtil.isNullOrEmpty(tbUser.getLoginName()) || StringUtil.isNullOrEmpty(tbUser.getPassword())) {
            log.error("租户名和密码不能为空");
            return ResultVo.error("租户名和密码不能为空");
        }
        //判断是否重名
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("login_name", tbUser.getLoginName());
        List<TbUser> list = tbUserService.list(queryWrapper);
        if (list.size() > 0) {
            log.error("租户名已存在");
            return ResultVo.error("租户名" + tbUser.getLoginName() + "已存在");
        }
        String password = DigestUtil.md5Hex16(tbUser.getPassword());
        tbUser.setPassword(password);
        tbUser.setCreateTime(LocalDateTime.now());
        if (tbUser.getExpireTime() != null) {
            tbUser.setExpireTime(tbUser.getExpireTime());
        }
        int i = tbUserService.saveAndInterface(tbUser);
        return ResultVo.success(i);
    }

    /**
     * 根据主键删除。
     *
     * @param id 主键
     * @return {@code true} 删除成功，{@code false} 删除失败
     */
    @DeleteMapping("remove/{id}")
    @LogOperation("租户-租户删除")
    public ResultVo remove(@PathVariable Integer id) {
        return ResultVo.success(tbUserService.removeById(id));
    }

    /**
     * 根据主键更新。
     *
     * @param tbUser
     * @return {@code true} 更新成功，{@code false} 更新失败
     */
    @Operation(summary = "更新租户信息", description = "更新租户信息")
    @LogOperation("租户-更新租户信息")
    @PutMapping("update")
    public ResultVo update(@RequestBody TbUser tbUser) {
        if (tbUser.getUpdateTime() != null) {
            tbUser.setUpdateTime(tbUser.getUpdateTime());
        }
        if (tbUser.getExpireTime() != null) {
            tbUser.setExpireTime(tbUser.getExpireTime());
        }
        tbUser.setPassword(null); // 密码不允许更新
        tbUser.setLoginName(null); // 登录名不允许更新
        tbUser.setCreateTime(null); // 创建时间不允许更新
        boolean b = tbUserService.updateById(tbUser);
        if (!b) {
            return ResultVo.error("更新失败，取消批量更新接口");
        }
        int i = tbUserInterfaceService.updateInterfaceByUserId(tbUser.getId(), tbUser.getTbInterfaceList());
        log.info("更新接口，updateInterfaceByUserId，结果：{}", i);
        return ResultVo.success("更新成功");
    }

    //密码修改
    @Operation(summary = "更新密码", description = "更新密码")
    @LogOperation("租户-更新密码")
    @PutMapping("updatePassword")
    public ResultVo updatePassword(@RequestBody PasswordVo passwordVo) {
        if (StringUtil.isNullOrEmpty(passwordVo.getOldPassword()) || StringUtil.isNullOrEmpty(passwordVo.getNewPassword())) {
            log.error("旧密码和新密码不能为空");
            return ResultVo.error("旧密码和新密码不能为空");
        }
        if (passwordVo.getOldPassword().equals(passwordVo.getNewPassword())) {
            log.error("新密码不能和旧密码相同");
            return ResultVo.error("新密码不能和旧密码相同");
        }
        Integer loginId = StpUtil.getLoginIdAsInt();
        if (loginId == null) {
            return ResultVo.error("未登录");
        }
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq(TB_USER.ID.getName(), loginId);
        queryWrapper.eq(TB_USER.PASSWORD.getName(), DigestUtil.md5Hex16(passwordVo.getOldPassword()));
        TbUser tbUser = tbUserService.getOne(queryWrapper);
        if (tbUser == null) {
            return ResultVo.error("旧密码错误");
        }
        tbUser.setPassword(DigestUtil.md5Hex16(passwordVo.getNewPassword()));
        tbUser.setUpdateTime(LocalDateTime.now());
        boolean b = tbUserService.updateById(tbUser);
//        if (b) {
//            StpUtil.logout(loginId);
//        }
        return ResultVo.success(b);
    }

    /**
     * 查询所有。
     *
     * @return 所有数据
     */
    @GetMapping("list")
    public ResultVo<List<TbUser>> list() {
        return ResultVo.success(tbUserService.list());
    }

    /**
     * 根据主键获取详细信息。
     *
     * @param id 主键
     * @return 详情
     */
    @GetMapping("getInfo/{id}")
    public ResultVo getInfo(@PathVariable Integer id) {
        return ResultVo.success(tbUserService.getById(id));
    }

    /**
     * 分页查询。
     *
     * @return 分页对象
     */
    @Operation(summary = "租户查询分页", description = "租户查询分页")
    @GetMapping("page")
    public ResultVo page(TbUser userQuery, @RequestParam(defaultValue = "1") int pageNumber,
                         @RequestParam(defaultValue = "10") int pageSize) {
        Page page = new Page(pageNumber, pageSize);
        QueryWrapper queryWrapper = new QueryWrapper();
        if (StringUtils.hasLength(userQuery.getName())) {
            queryWrapper.like("name", userQuery.getName());
        }
        if (StringUtils.hasLength(userQuery.getCode())) {
            queryWrapper.eq("code", userQuery.getCode());
        }
        if (StringUtils.hasLength(userQuery.getAddress())) {
            queryWrapper.like("address", userQuery.getAddress());
        }
        if (StringUtils.hasLength(userQuery.getStatus())) {
            queryWrapper.eq("status", userQuery.getStatus());
        }
        if (StringUtils.hasLength(userQuery.getIndustry())) {
            queryWrapper.eq("industry", userQuery.getIndustry());
        }
        queryWrapper.orderBy("id", false);
        return ResultVo.success(tbUserService.page(page, queryWrapper));
    }

}
